package com.hlg.xboot.web.controller.mobile.sdk;

import com.hlg.xboot.constants.AppConstants;
import com.hlg.xboot.enums.Channel;
import com.hlg.xboot.exceptions.ParameterException;
import com.hlg.xboot.exceptions.ServerBizException;
import com.hlg.xboot.model.modules.User;
import com.hlg.xboot.service.modules.UserService;
import com.hlg.xboot.vo.RestBody;
import com.hlg.xboot.web.controller.BaseController;
import com.digi_zones.common.utils.ResponseUtils;
import com.digi_zones.common.wechat.TokenHelper;
import com.digi_zones.common.wechat.WeChatConstants;
import com.digi_zones.common.wechat.entity.AccessToken;
import com.digi_zones.common.wechat.entity.JSAPITicket;
import com.digi_zones.common.wechat.entity.user.UserInfo;
import com.digi_zones.common.wechat.service.AccessTokenService;
import com.digi_zones.common.wechat.service.SignService;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.collections.map.HashedMap;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.ServletRequestUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
 * <p>微信公众号接口</p>
 * <p>Copyright: Copyright (c) 2016</p>
 * @author 杨信
 * @version 1.0
 * @date 2016/12/26
 */
@Controller("weChatControllerSDK")
@RequestMapping("/wechat")
public class WeChatController extends BaseController {

    @Autowired
    private TokenHelper tokenHelper;
    @Autowired
    private UserService userService;

    /**
     * 获取微信公众号网页授权url
     */
    @RequestMapping(value = "/authurl", method = RequestMethod.GET)
    public RestBody getAuthConfig(HttpServletRequest request) throws Exception {
        String callback = appConfig.getServer() +  "/wechat/callback";
        String redictUrl = URLEncoder.encode(callback, "utf-8");
        String apiToken = request.getSession().getId();
        String authUrl = AccessTokenService.getAuthorizeUrl(appConfig.getWeixin().getAppid(),
                redictUrl, WeChatConstants.SCOPE_SNSAPI_USERINFO, apiToken);
        Map<String,Object> data = new HashedMap();
        data.put(AppConstants.API_TOKEN,apiToken);
        data.put("authUrl", authUrl);
        return success(data);
    }

    /**
     * 微信公众号网页授权回调
     */
    @RequestMapping(value = "/callback")
    public void callback(HttpServletRequest request, HttpServletResponse response) throws Exception {
        String code = ServletRequestUtils.getStringParameter(request, "code");
        String apiToken = ServletRequestUtils.getStringParameter(request, "state");
        logger.info("loginCallback-->code:{}, state:{}", code, apiToken);
        if (StringUtils.isEmpty(code) || StringUtils.isEmpty(apiToken)) {
            logger.error("非法请求，无效的授权code: {} authApiToken: {}", code, apiToken);
            response.sendRedirect(appConfig.getApp());
            return;
        }

        // 获取授权access token
        AccessToken accessToken = tokenHelper.getAccessAuthorizeTokenForCache(apiToken, code);
        if (accessToken == null) {
            logger.error(String.format("获取授权access token失败， code: %s, state: %s", code, apiToken));
            response.sendRedirect(appConfig.getApp());
            return;
        }

        // 如果用户已经存在,直接返回到首页
        User user = userService.findByOpenid(accessToken.getOpenid());
        if (user != null) {
            response.sendRedirect(appConfig.getApp());
            return;
        }

        UserInfo userInfo = com.digi_zones.common.wechat.service.UserService.getUserInfo(accessToken.getAccess_token(), accessToken.getOpenid());
        if (userInfo == null) {
            logger.error("获取微信用户信息失败");
            response.sendRedirect(appConfig.getApp());
            return;
        }
        user = saveWechatUser(userInfo);
        response.sendRedirect(appConfig.getApp() + "?openid=" + user.getOpenid());
    }

    /**
     * 保存微信用户信息
     * @param userInfo 微信用户信息
     * @return
     */
    private User saveWechatUser(UserInfo userInfo) {
        User user = new User();
        user.setOpenid(userInfo.getOpenid());
        user.setNickname(userInfo.getNickname());
        user.setAvatar(userInfo.getHeadimgurl());
        user.setSex(userInfo.getSex());
        user.setProvince(userInfo.getProvince());
        user.setCity(userInfo.getCity());
        user.setChannel(Channel.WECHAT.getValue());
        userService.add(user);
        return user;
    }

    /**
     * JS API配置
     */
    @RequestMapping(value = "/jsconfig", method = RequestMethod.GET)
    public void jsConfig(String surl, HttpServletRequest request, HttpServletResponse response) throws Exception {
        if (StringUtils.isEmpty(surl)) {
            throw new ParameterException("签名URL为空");
        }

        String timestamp = Long.toString(System.currentTimeMillis() / 1000);
        String nonceStr = UUID.randomUUID().toString();
        JSAPITicket ticket = tokenHelper.getJSAPITicketForCache();
        if (ticket == null) {
            throw new ServerBizException("获取微信JSAPITicket失败");
        }
        String str = String.format("jsapi_ticket=%s&noncestr=%s&timestamp=%s&url=%s", ticket.getTicket(), nonceStr, timestamp, surl);
        String signature = DigestUtils.sha1Hex(str);
        Map<String, Object> config = new HashMap<>();
        config.put("timestamp", timestamp);
        config.put("nonceStr", nonceStr);
        config.put("signature", signature);
        config.put("appId", appConfig.getWeixin().getAppid());
        ResponseUtils.responseSuccess(response, config);
    }


    /**
     * 微信token验证
     * @param echostr
     * @param signature
     * @param timestamp
     * @param nonce
     * @param request
     * @param response
     * @return
     */
    @RequestMapping(value = "/signature", method = RequestMethod.GET)
    @ResponseBody
    public String checkSignature(String echostr, String signature, String timestamp, String nonce, HttpServletRequest request, HttpServletResponse response) {
        boolean res = SignService.checkSignature(signature, appConfig.getWeixin().getMessageToken(), timestamp, nonce);
        if (res) {
            return echostr;
        }
        return null;
    }

}
